
/* Generated by Interface Builder */

#import "GraphView.h"
#import "GraphController.h"
#import <math.h>
#import <dpsclient/wraps.h>
#import <appkit/appkit.h>
#import "DrawPoly.h"

float sinTheta=0.0,cosTheta=0.0,sinPhi=0.0,cosPhi=0.0, perspective=0.0, vanish=0.0, halfSize=0.0;
int xSlider, ySlider, size=0;
float mouseScale=0.4;
float xStart=0.0, yStart=0.0;


void Rotate(px, py, pz)
	float *px, *py, *pz;
{
	float xt=0.0, yt=0.0;

	xt = *pz * sinTheta + *px * cosTheta;
	*pz = *pz * cosTheta - *px * sinTheta;
	*px = xt;

	yt = *py * cosPhi - *pz * sinPhi;
	*pz = *py * sinPhi + *pz * cosPhi;
	*py = yt;

	xt = (vanish-*pz * perspective) / vanish;
	*px = *px * xt;
	*py = *py * xt;
}

void DrawPolygon(curPoly)
	PointThreeD curPoly[];
{
	Rotate(&curPoly[0].x, &curPoly[0].y, &curPoly[0].z);
	Rotate(&curPoly[1].x, &curPoly[1].y, &curPoly[1].z);
	Rotate(&curPoly[2].x, &curPoly[2].y, &curPoly[2].z);

	DrawPoly3(curPoly[0].x+xStart, curPoly[0].y+yStart,
		  curPoly[1].x+xStart, curPoly[1].y+yStart,
		  curPoly[2].x+xStart, curPoly[2].y+yStart);
}

void FillPolygon(curPoly, gray)
	PointThreeD curPoly[];
	float gray;
{
	Rotate(&curPoly[0].x, &curPoly[0].y, &curPoly[0].z);
	Rotate(&curPoly[1].x, &curPoly[1].y, &curPoly[1].z);
	Rotate(&curPoly[2].x, &curPoly[2].y, &curPoly[2].z);

	FillPoly3(curPoly[0].x+xStart, curPoly[0].y+yStart,
		  curPoly[1].x+xStart, curPoly[1].y+yStart,
		  curPoly[2].x+xStart, curPoly[2].y+yStart, gray);
}


void DrawPolygon4(curPoly)
	PointThreeD curPoly[];
{
	Rotate(&curPoly[0].x, &curPoly[0].y, &curPoly[0].z);
	Rotate(&curPoly[1].x, &curPoly[1].y, &curPoly[1].z);
	Rotate(&curPoly[2].x, &curPoly[2].y, &curPoly[2].z);
	Rotate(&curPoly[3].x, &curPoly[3].y, &curPoly[3].z);

	DrawPoly4(curPoly[0].x+xStart, curPoly[0].y+yStart,
		  curPoly[1].x+xStart, curPoly[1].y+yStart,
		  curPoly[2].x+xStart, curPoly[2].y+yStart,
		  curPoly[3].x+xStart, curPoly[3].y+yStart);
}


/***************************************************************/

@implementation GraphView

- initFrame:(const NXRect *)r
{
	[super initFrame:r];
	yScale = 0.1;
	xSize=r->size.width;
	ySize=r->size.height;
	xStart = xSize / 2;
	yStart = ySize / 2;
	return self;
}

- drawSelf:(const NXRect *)r: (int)c;
{
	PSsetgray(1.0);
	NXRectFill(r);

	[self drawGraph:[graphControllerPtr readDetail]:
				[graphControllerPtr readTheta]:
				[graphControllerPtr readPhi]:
				[graphControllerPtr readGraphArray]];

	[self drawBoundingBox: [graphControllerPtr readTheta]: [graphControllerPtr readPhi]];
/*	[self drawAxes: [graphControllerPtr readTheta]: [graphControllerPtr readPhi]];
*/
	return self;
}

- drawAxes: (int)theta: (int)phi
{
	PointThreeD curPoly[3];
	float x1=0,y1=0,z1=0,x2=0,y2=0,z2=0;

	sinTheta = sin(theta/180.0*PI);
	sinPhi = sin(-phi/180.0*PI);
	cosTheta = cos(theta/180.0*PI);
	cosPhi = cos(-phi/180.0*PI);

	PSsetgray(0);
	PSsetlinewidth(2);
	
	x1 = -halfSize; y1 = -halfSize; z1 = -halfSize;
	x2 =  halfSize; y2 = -halfSize; z2 = -halfSize;
	Rotate(&x1, &y1, &z1);
	Rotate(&x2, &y2, &z2);
	PSmoveto(x1+xStart, y1+yStart);
	PSlineto(x2+xStart, y2+yStart);
	PSstroke();
	PSmoveto(x2*.9+xStart, y2*.9+yStart);
	PSshow("X");

	x1 = -halfSize; y1 = -halfSize; z1 = -halfSize;
	x2 = -halfSize; y2 =  halfSize; z2 = -halfSize;
	Rotate(&x1, &y1, &z1);
	Rotate(&x2, &y2, &z2);
	PSmoveto(x1+xStart, y1+yStart);
	PSlineto(x2+xStart, y2+yStart);
	PSstroke();
	PSmoveto(x2*.9+xStart, y2*.9+yStart);
	PSshow("Y");

	x1 = -halfSize; y1 = -halfSize; z1 = -halfSize;
	x2 = -halfSize; y2 = -halfSize; z2 =  halfSize;
	Rotate(&x1, &y1, &z1);
	Rotate(&x2, &y2, &z2);
	PSmoveto(x1+xStart, y1+yStart);
	PSlineto(x2+xStart, y2+yStart);
	PSstroke();
	PSmoveto(x2*.9+xStart, y2*.9+yStart);
	PSshow("Z");

	curPoly[0].x = halfSize;     curPoly[0].y =  -halfSize;     curPoly[0].z = -halfSize;
	curPoly[1].x = halfSize*.9;  curPoly[1].y = -halfSize*.97;  curPoly[1].z = -halfSize;
	curPoly[2].x = halfSize*.9;  curPoly[2].y = -halfSize*1.03; curPoly[2].z = -halfSize;
	FillPolygon(curPoly,0);

	curPoly[0].x = -halfSize;   curPoly[0].y = halfSize;     curPoly[0].z = -halfSize;
	curPoly[1].x = -halfSize;   curPoly[1].y = halfSize*.9;  curPoly[1].z = -halfSize*.97;
	curPoly[2].x = -halfSize;   curPoly[2].y = halfSize*.9;  curPoly[2].z = -halfSize*1.03;
	FillPolygon(curPoly,0);

	curPoly[0].x = -halfSize;      curPoly[0].y = -halfSize;  curPoly[0].z = halfSize;
	curPoly[1].x = -halfSize*.97;  curPoly[1].y = -halfSize;  curPoly[1].z = halfSize*.9;
	curPoly[2].x = -halfSize*1.03; curPoly[2].y = -halfSize;  curPoly[2].z = halfSize*.9;
	FillPolygon(curPoly,0);

	
	curPoly[0].x = halfSize;     curPoly[0].y =  -halfSize;     curPoly[0].z = -halfSize;
	curPoly[1].x = halfSize*.9;  curPoly[1].y = -halfSize;  curPoly[1].z = -halfSize*.97;
	curPoly[2].x = halfSize*.9;  curPoly[2].y = -halfSize; curPoly[2].z = -halfSize*1.03;
	FillPolygon(curPoly,0);

	curPoly[0].x = -halfSize;   curPoly[0].y = halfSize;     curPoly[0].z = -halfSize;
	curPoly[1].x = -halfSize*.97;   curPoly[1].y = halfSize*.9;  curPoly[1].z = -halfSize;
	curPoly[2].x = -halfSize*1.03;   curPoly[2].y = halfSize*.9;  curPoly[2].z = -halfSize;
	FillPolygon(curPoly,0);

	curPoly[0].x = -halfSize;      curPoly[0].y = -halfSize;  curPoly[0].z = halfSize;
	curPoly[1].x = -halfSize;  curPoly[1].y = -halfSize*.97;  curPoly[1].z = halfSize*.9;
	curPoly[2].x = -halfSize; curPoly[2].y = -halfSize*1.03;  curPoly[2].z = halfSize*.9;
	FillPolygon(curPoly,0);


	PSsetlinewidth(1);
	return self;
}


- drawBoundingBox: (int)theta: (int)phi
{
	PointThreeD curPoly[4];

	sinTheta = sin(theta/180.0*PI);
	sinPhi = sin(-phi/180.0*PI);
	cosTheta = cos(theta/180.0*PI);
	cosPhi = cos(-phi/180.0*PI);
	
	PSsetgray(0.333);

	curPoly[0].x = -halfSize; curPoly[0].y = -halfSize; curPoly[0].z = -halfSize;
	curPoly[1].x =  halfSize; curPoly[1].y = -halfSize; curPoly[1].z = -halfSize;
	curPoly[2].x =  halfSize; curPoly[2].y =  halfSize; curPoly[2].z = -halfSize;
	curPoly[3].x = -halfSize; curPoly[3].y =  halfSize; curPoly[3].z = -halfSize;
	DrawPolygon4(curPoly);

	curPoly[0].x = -halfSize; curPoly[0].y = -halfSize; curPoly[0].z =  halfSize;
	curPoly[1].x =  halfSize; curPoly[1].y = -halfSize; curPoly[1].z =  halfSize;
	curPoly[2].x =  halfSize; curPoly[2].y =  halfSize; curPoly[2].z =  halfSize;
	curPoly[3].x = -halfSize; curPoly[3].y =  halfSize; curPoly[3].z =  halfSize;
	DrawPolygon4(curPoly);

	curPoly[0].x = -halfSize; curPoly[0].y = -halfSize; curPoly[0].z = -halfSize;
	curPoly[1].x = -halfSize; curPoly[1].y = -halfSize; curPoly[1].z =  halfSize;
	curPoly[2].x = -halfSize; curPoly[2].y =  halfSize; curPoly[2].z =  halfSize;
	curPoly[3].x = -halfSize; curPoly[3].y =  halfSize; curPoly[3].z = -halfSize;
	DrawPolygon4(curPoly);

	curPoly[0].x =  halfSize; curPoly[0].y = -halfSize; curPoly[0].z = -halfSize;
	curPoly[1].x =  halfSize; curPoly[1].y = -halfSize; curPoly[1].z =  halfSize;
	curPoly[2].x =  halfSize; curPoly[2].y =  halfSize; curPoly[2].z =  halfSize;
	curPoly[3].x =  halfSize; curPoly[3].y =  halfSize; curPoly[3].z = -halfSize;
	DrawPolygon4(curPoly);

	return self;
}

- drawGraph:(int)detail: (int)theta: (int)phi: (bigArray)graphArray
{
	int i=0,j=0, xCount=0, zCount=0;
	PointThreeD curPoly[4];
	
	float partScale=0.0;
	float count=0.0;
	
	count=PI/detail*4;

	sinTheta = sin(theta/180.0*PI);
	sinPhi = sin(-phi/180.0*PI);
	cosTheta = cos(theta/180.0*PI);
	cosPhi = cos(-phi/180.0*PI);
	size = [graphControllerPtr readSize];
	perspective = [graphControllerPtr readPerspective];
	halfSize = size / 2;
	partScale=size / detail;
	vanish = size;

	PSsetgray(0);
	for (i=0; i<detail; i++)
	{
		zCount = i-detail / 2;
		for (j=0; j<detail; j++)
		{
			xCount = j - detail / 2;
			curPoly[0].x=xCount*partScale;
			curPoly[0].y=sin(i*count)*cos(j*count)*partScale;
			curPoly[0].z=zCount*partScale;
			
			curPoly[1].x=xCount*partScale;
			curPoly[1].y=sin((i+1)*count)*cos(j*count)*partScale;
			curPoly[1].z=(zCount+1)*partScale;

			curPoly[2].x=(xCount+1)*partScale;
			curPoly[2].y=sin((i+1)*count)*cos((j+1)*count)*partScale;
			curPoly[2].z=(zCount+1)*partScale;

			curPoly[3].x=(xCount+1)*partScale;
			curPoly[3].y=sin(i*count)*cos((j+1)*count)*partScale;
			curPoly[3].z=zCount*partScale;

			DrawPolygon4(curPoly);
		}
	}
	
	return self;
}

- mouseDown:(NXEvent *)e
{
	NXPoint startPoint;
	
	oldMask = [window addToEventMask:NX_MOUSEDRAGGEDMASK];
	startPoint = e->location;
	xSlider = (int) (startPoint.x);
	ySlider = (int) (startPoint.y);
	return self;
}	

- mouseDragged:(NXEvent *)e
{
	NXPoint	currentPoint;	
	int tempX, tempY;

	currentPoint = e->location;
	tempX = (int) currentPoint.x;
	tempY = (int) currentPoint.y;
	tempX = (int) (tempX - xSlider)*mouseScale;
	tempY = (int) (tempY - ySlider)*mouseScale;

	if ((tempX != 0) || (tempY != 0))
	{
		tempX=[graphControllerPtr readTheta]+tempX;
		if (tempX > 180) tempX=180;
		if (tempX < -180) tempX=-180;
		[graphControllerPtr writeTheta:tempX];
		[graphControllerPtr slideThetaSlider:tempX];
		tempY=[graphControllerPtr readPhi]+tempY;
		if (tempY > 90) tempY=90;
		if (tempY < -90) tempY=-90;
		[graphControllerPtr writePhi:tempY];
		[graphControllerPtr slidePhiSlider:tempY];
		[self display];
		NXPing();
		xSlider = (int) currentPoint.x;
		ySlider = (int) currentPoint.y;
	}
	return self;
}

- mouseUp:(NXEvent *)e
{
	[window setEventMask:oldMask];
	return self;
}


@end
